import importlib
import subprocess
import struct
from utils import SettingUtil,FileUtil

__CONFIG_MODULE__ = None

def writeAndCompilePB(protoContent):
    usePb = SettingUtil.getSetting().usePB
    if usePb:
        moduleName = SettingUtil.getSetting().configModule
        configPbFile =  SettingUtil.getSetting().configPbFile
        FileUtil.writeTextFile(configPbFile,protoContent)
        compilePB(moduleName)

def compilePB(configName):
    protoFile = configName+".proto"
    print(f"开始编译 {protoFile} 文件")
    protoRoot = SettingUtil.getSetting().protoRoot
    cmd = [f"./{protoRoot}/protoc.exe",f"-I=./{protoRoot}","--python_out=./protoCmd","--pyi_out=./protoCmd",protoFile]
    if subprocess.call(cmd) !=0:
        raise Exception(f"编译{protoFile}失败")
    print(f"编译 {protoFile} 文件完成")

def importModule(moduleName):
    global __CONFIG_MODULE__
    if __CONFIG_MODULE__ == None:
        __CONFIG_MODULE__ = importlib.import_module(f"protoCmd.{moduleName}") #动态加载模块

def instanceMessage(moduleName,clsName):
    importModule(moduleName)
    global __CONFIG_MODULE__
    cls = getattr(__CONFIG_MODULE__,clsName) #动态获取模块的类
    return cls()

#把数据从字节数组转换成list或dict
def byteToMessageCollect(byteArr:bytes,moduleName,clsName):
    #print("++++++++++++++")
    st = 0
    sizeLen = 4
    M = struct.unpack("<i",byteArr[st:sizeLen])[0] #读取数据总行数
    #print("toMessageArray count=",count)
    st += sizeLen
    keySize = 2
    keyLen = struct.unpack("<H",byteArr[st:st+keySize])[0] #读取数据主键长度 2个字节
    print("toMessageArray keyLen=",keyLen)
    st += keySize
    keyStr = ""
    msgCollect = []
    isKey = keyLen > 0
    if isKey:
        keyStr = byteArr[st:st+keyLen].decode(encoding="utf8")
        st += keyLen
        print(f"byteToMessageCollect 表格{clsName}读取到key，返回dict keyStr=",keyStr)
        msgCollect = {}
    for i in range(M):
        size = struct.unpack("<i",byteArr[st:st+sizeLen])[0] #当前行数据的大小
        st = st + sizeLen
        msg = instanceMessage(moduleName,clsName) #实例化PB对象
        tempBytes =  byteArr[st:st+size]
        st = st+size
        msg.ParseFromString(tempBytes)
        if isKey:
            msgCollect[getMsgKeyStr(msg,keyStr)] = msg
        else:
            msgCollect.append(msg)
    print(f"byteToMessageCollect {clsName}={len(msgCollect)}")
    return msgCollect

def getMsgKeyStr(msg,keyFieldStr):
    keyArr = keyFieldStr.split("_")
    keyStr = ""
    count = len(keyArr)
    for i in range(count):
        item = keyArr[i]
        if item !="":
            keyStr +=str(getattr(msg,item))
            keyStr+="_"
    keyStr = keyStr[:-1]
    return keyStr

def sheetNameToModuleName(sheetName:str)->str:
    return sheetName + "_pb2"

